﻿#include "stdafx.h"
#include "widget.h"
#include "ui_widget.h"
#include "opendoor.h"
#include "ipfetcher.h"
#include "common.h"

#include <QtNetwork>
#include <QMessageBox>
#include <thread>
#include <future>


Widget::Widget(QWidget *parent) :
QDialog(parent),
ui(new Ui::Widget)
{
    ui->setupUi(this);
    enableOpen();

    loadMacList();
    initMacList();

    // show ststus
    ui->plainTextEdit_status->setPlainText("");
    showStatus("program running!");

    // fetch ip and show the tips of the ip fetched.
    fetchIp();
    if (!isIpFetched())
    {
        autoFixProblems();
    }

    // auto fetch new ip address.
    startAutoFetchIP();

}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_editIP_clicked()
{
    QString ipStr = QInputDialog::getText(this,
                                          "Edit IP by yourself",
                                          "New IP :");
    QHostAddress ip(ipStr);
    if (ip.toIPv4Address())
        this->ui->label_ip->setText(ipStr);
}


void Widget::on_pushButton_exit_clicked()
{
    this->close();
}

void Widget::on_pushButton_addMac_clicked()
{
    QString mac = QInputDialog::getText(this,
                                          "Add MAC",
                                          "Please input a MAC address : ",
                                          QLineEdit::Normal,
                                          ui->comboBox_mac->currentText());
    if (mac.isEmpty())
        return;
    correctMac(mac);
    if (!isIpclientMac(mac))
    {
        QMessageBox::critical(this, "error!", QU("This is not a correct MAC address!"));
        return;
    }
    addMacToList(mac);

    ui->comboBox_mac->setCurrentIndex(ui->comboBox_mac->findText(mac));
    saveMacList();
}

void Widget::on_pushButton_deleteMac_clicked()
{
    QComboBox *comBox = ui->comboBox_mac;
    comBox->removeItem(comBox->currentIndex());
    saveMacList();

}

void Widget::on_pushButton_open_clicked()
{
    QString str = ui->comboBox_mac->currentText();
    QString correctedMac = correctMac(str);
    Data::Operaction operaction = Data::Operaction::CmccOpen;
    if (ui->comboBox_server->currentText() == "Telecom")
    {
        operaction = Data::Operaction::TelecomOpen;
    }
    else if (ui->comboBox_server->currentText() == "Unioncom")
    {
        operaction = Data::Operaction::UnioncomOpen;
    }
    else /*if (ui->comboBox_server->text() == "Cmcc")*/
    {
        operaction = Data::Operaction::CmccOpen;
    }
    if (openDoor(ui->label_ip->text(), correctMac(str), operaction))
    {
        showStatus(QU("Sent the Datagram successfully, enjoy your self!"));
    }
    else
        showStatus(QU("Failed to send the Datagram, please check your network environment."));
}

/* add a ipclient style mac to the address list
 * if there is some thing wrong with the mac address, it does nothing.*/
void Widget::addMacToList(QString mac, const QString &remark /* = "" */)
{
    correctMac(mac);
    if (!isIpclientMac(mac))
        return;

    QComboBox *combobox = ui->comboBox_mac;
    for (int i = 0; i < combobox->count(); i++)
    {
        const QString &str = combobox->itemText(i);
        QString thismac, thisremark;
        getMacAndRemarkFromMacString(str, thismac, thisremark);
        if (thismac == mac)
        {
            if (thisremark == remark)
                return;
            else
            {
                combobox->setItemText(i, combineMacAndRemark(mac, remark));
                return;
            }
        }
    }
    combobox->addItem(combineMacAndRemark(mac, remark));
}

QString Widget::fetchIp() const
{
    QString ip = ::fetchIP().toString();
    ui->label_ip->setText(ip);
    return ip;
}

void Widget::showStatus(QString status)
{
    QPlainTextEdit *w = ui->plainTextEdit_status;
    status.replace("\n", "    \n");
    w->setPlainText(QTime::currentTime().toString("hh:mm:ss") % " :\n    " % status % "\n\n" % w->toPlainText());
}

void Widget::disableOpen()
{
    ui->pushButton_open->setEnabled(false);
    ui->pushButton_open->setStyleSheet("*{color:red}");
    ui->label_ip->setStyleSheet("*{color:red}");
    ui->pushButton_open->setText(QU("Network error!"));
}

void Widget::enableOpen()
{
    ui->pushButton_open->setEnabled(true);
    ui->pushButton_open->setStyleSheet("*{color:blue}");
    ui->label_ip->setStyleSheet("*{color:blue}");
    ui->pushButton_open->setText(QU("MAC is choosed , open the door!"));
}

void Widget::saveMacList()
{
    QComboBox *comBox = ui->comboBox_mac;
    QFile macFile("macList.txt");
    if (macFile.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QTextStream s(&macFile);
        for (int i = comBox->count() - 1; i > 0; i--)
        {
            QString mac = comBox->itemText(i);
            s << mac << "\n";
        }
    }
}

void Widget::loadMacList()
{
    QFile macFile("macList.txt");
    if (macFile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QStringList localList;
        QStringList customList;
        QTextStream s(&macFile);
        while (!s.atEnd())
        {
            QString str;
            s >> str;

            addMyMacString(str);
        }
    }
}

void Widget::initMacList()
{
    auto interfaces = QNetworkInterface::allInterfaces();
    for (const QNetworkInterface &i : interfaces)
    {
        addMacToList(i.hardwareAddress(), "local");
    }
}

void Widget::getMacAndRemarkFromMacString(const QString &str, QString &mac, QString &remark)
{
    mac = str.left(17);
    remark = str.mid(17 + 1);
    remark = remark.left(remark.lastIndexOf(')'));
}

void Widget::addMyMacString(const QString &str)
{
    QString mac, remark;
    getMacAndRemarkFromMacString(str, mac, remark);
    addMacToList(mac, remark);
}

QString Widget::combineMacAndRemark(const QString &mac, const QString &remark)
{
    if (!remark.isEmpty())
        return mac % "(" % remark % ")";
    return mac;
}

bool Widget::showIpTips(const QString &ip)
{
    if (!ip.isEmpty())
    {
        showStatus(QU("Got your IP."));
        if (ip.contains("169."))
        {
            disableOpen();
            showStatus(QU(
                "error :" "Can't handle this situation~\n"
                "see FAQ1 and FAQ3 please."));
            return false;
        }
        else
        {
            if (ip.contains("172.19"))
            {
                showStatus(QU("Your network environment is so perfect!."));
            }
            enableOpen();
            return true;
        }
    }
    else
    {
        ui->label_ip->setText(QU("Cann't connect to Network Centrol."));
        disableOpen();
        showStatus(QU(
            "Cann't connect to Network Centrol!\n"
            "See FAQ1 please!"));
        return false;
    }
}

void Widget::startAutoFetchIP()
{
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, [&, timer]()
    {
        if (isIpFetched())
        {
            timer->stop();
            showIpTips(ui->label_ip->text());
        }
        else
        {
            std::async([this]()
            {
                this->fetchIp();
            });
        }
    });
    timer->start(2000);
}

bool Widget::isIpFetched()
{
    auto ipv4 = QHostAddress(ui->label_ip->text()).toIPv4Address();
    return  ipv4 & 0xFF
        && ipv4 & 0xFF00
        && ipv4 & 0xFF0000
        && ipv4 & 0xFF000000;
}

void Widget::autoFixProblems()
{ }
